package com.benshou.bsoa.common.util;

import com.benshou.bsoa.common.trace.UserContext;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.BeanProperty;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.ser.ContextualSerializer;

import java.io.IOException;
import java.time.*;
import java.time.format.DateTimeFormatter;
import java.time.temporal.TemporalAccessor;
import java.util.Date;

public class DynamicTimezoneSerializer extends JsonSerializer<Object> 
    implements ContextualSerializer {

    private DateTimeFormatter formatter;
    private String pattern;

    // 默认构造方法（Jackson 反射需要）
    public DynamicTimezoneSerializer() {}

    // 带参数的构造方法（用于创建上下文序列化器）
    public DynamicTimezoneSerializer(String pattern) {
        this.pattern = pattern;
        this.formatter = DateTimeFormatter.ofPattern(pattern);
    }

    @Override
    public void serialize(Object value, JsonGenerator gen, SerializerProvider provider) 
        throws IOException {
        
        // 1. 获取客户端时区（取值 UserContext）
        ZoneId targetZone = ZoneId.of(UserContext.getClientTimezone());

        // 2. 转换为目标时区的 TemporalAccessor
        TemporalAccessor temporal = convertToTemporal(value, targetZone);

        // 3. 格式化并写入 JSON
        gen.writeString(formatter.format(temporal));
    }

    private TemporalAccessor convertToTemporal(Object value, ZoneId targetZone) {
        // 处理不同日期时间类型
        if (value instanceof Date) {
            return ((Date) value).toInstant().atZone(targetZone);
        } else if (value instanceof Instant) {
            return ((Instant) value).atZone(targetZone);
        } else if (value instanceof ZonedDateTime) {
            return ((ZonedDateTime) value).withZoneSameInstant(targetZone);
        } else if (value instanceof LocalDateTime) {
            // 假设 LocalDateTime 基于系统默认时区
            return ((LocalDateTime) value).atZone(ZoneId.systemDefault()).withZoneSameInstant(targetZone);
        } else if (value instanceof LocalDate) {
            // LocalDate 无时间部分，转换为目标时区的当天起始时间
            return ((LocalDate) value).atStartOfDay(targetZone);
        } else {
            throw new IllegalArgumentException("Unsupported type: " + value.getClass().getName());
        }
    }

    @Override
    public JsonSerializer<?> createContextual(SerializerProvider prov, BeanProperty property) {
        // 从字段注解中提取 pattern
        JsonFormat format = (property != null) ? property.getAnnotation(JsonFormat.class) : null;
        String pattern = (format != null && !format.pattern().isEmpty()) 
            ? format.pattern() 
            : "yyyy-MM-dd HH:mm:ss";

        // 检查 pattern 与类型的兼容性
        if (property != null) {
            Class<?> type = property.getType().getRawClass();
            validatePattern(pattern, type);
        }

        return new DynamicTimezoneSerializer(pattern);
    }

    private void validatePattern(String pattern, Class<?> type) {
        boolean isDateOnly = pattern.contains("yyyy-MM-dd") && !pattern.contains("HH:mm:ss");
        if (LocalDate.class.isAssignableFrom(type) && !isDateOnly) {
            throw new IllegalArgumentException("LocalDate 字段不能使用包含时间的格式: " + pattern);
        }
    }
}